package com.mystore.framework.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mystore.common.utils.security.Md5Utils;
import com.mystore.framework.mapper.UserMapper;
import com.mystore.framework.pojo.AppModel;
import com.mystore.framework.pojo.LoginUser;
import com.mystore.framework.pojo.Role;
import com.mystore.framework.pojo.User;

import com.mystore.framework.service.BaseService;
import icu.mhb.mybatisplus.plugln.base.mapper.JoinBaseMapper;
import icu.mhb.mybatisplus.plugln.base.service.impl.JoinServiceImpl;
import icu.mhb.mybatisplus.plugln.core.JoinLambdaWrapper;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class IUserServiceImpl extends IBaseServiceImpl<UserMapper,User> {
    @Resource
    private AuthenticationManager authenticationManager;
    @Resource
    private AuthorRedisServiceImpl authorRedisServiceImpl;
    @Transactional
    @Override
    public int insertOne(User user) {
        user.setUserPassword(Md5Utils.getMd5(user.getUserPassword()));
        System.err.println(user.getRoleId());
        return super.insertOne(user)==0?0:user.getUserId();
    }
    @Transactional
    @Override
    public boolean updateOne(User user) {
        if(user.getUserNewPassword()!=null&&!Objects.equals(Md5Utils.getMd5(user.getUserNewPassword()), user.getUserPassword())){
            user.setUserPassword(Md5Utils.getMd5(user.getUserNewPassword()));
            authorRedisServiceImpl.delete("user-id-"+user.getUserId());
        }
        return super.updateOne(user);
    }
    public User selectByEmail(String email) {
        JoinLambdaWrapper<User> queryWrapper=new JoinLambdaWrapper<>(User.class);
        queryWrapper.leftJoin(Role.class,Role::getRoleId,User::getRoleId)
                .oneToOneSelect(User::getRole, Role.class)
                .end();
        QueryWrapper<User> userQueryWrapper=new QueryWrapper<>();
        userQueryWrapper.eq("user_email",email);
        queryWrapper.changeQueryWrapper(userQueryWrapper);

        User result=baseMapper.joinSelectOne(queryWrapper, User.class);
        return result;
    }
    public User selectById(int id) {
        JoinLambdaWrapper<User> queryWrapper=new JoinLambdaWrapper<>(User.class);
        queryWrapper.leftJoin(Role.class,Role::getRoleId,User::getRoleId)
                .oneToOneSelect(User::getRole, Role.class)
                .end();
        QueryWrapper<User> userQueryWrapper=new QueryWrapper<>();
        userQueryWrapper.eq("user_id",id);
        queryWrapper.changeQueryWrapper(userQueryWrapper);

        User result=baseMapper.joinSelectOne(queryWrapper, User.class);
        return result;
    }
    public List<User> selectAll() {
        JoinLambdaWrapper<User> queryWrapper=new JoinLambdaWrapper<>(User.class);
        queryWrapper.leftJoin(Role.class,Role::getRoleId,User::getRoleId)
                .oneToOneSelect(User::getRole, Role.class)
                .end();
        List<User> userList=baseMapper.joinSelectList(queryWrapper,User.class);
        return userList;
    }
    public User selectByUserEmail(String email) {
        JoinLambdaWrapper<User> queryWrapper=new JoinLambdaWrapper<>(User.class);
        queryWrapper.leftJoin(Role.class,Role::getRoleId,User::getRoleId)
                .oneToOneSelect(User::getRole, Role.class)
                .end();
        QueryWrapper<User> userQueryWrapper=new QueryWrapper<>();
        userQueryWrapper.eq("user_email",email);
        userQueryWrapper.eq("enabled",1);
        userQueryWrapper.or().eq("enabled",-1);
        queryWrapper.changeQueryWrapper(userQueryWrapper);
        return baseMapper.joinSelectOne(queryWrapper,User.class);
    }
    public User selectNotCompleteRegister(String email) {
        JoinLambdaWrapper<User> queryWrapper=new JoinLambdaWrapper<>(User.class);
        queryWrapper.leftJoin(Role.class,Role::getRoleId,User::getRoleId)
                .oneToOneSelect(User::getRole, Role.class)
                .end();
        QueryWrapper<User> userQueryWrapper=new QueryWrapper<>();
        userQueryWrapper.eq("user_email",email);
        userQueryWrapper.eq("enabled",0);
        queryWrapper.changeQueryWrapper(userQueryWrapper);
        return baseMapper.joinSelectOne(queryWrapper,User.class);
    }
    public IPage<User> selectPage(Page<User> page) {
        JoinLambdaWrapper<User> queryWrapper=new JoinLambdaWrapper<>(User.class);
        queryWrapper.leftJoin(Role.class,Role::getRoleId,User::getRoleId)
                .oneToOneSelect(User::getRole, Role.class)
                .end();
        IPage<User> resultPage=baseMapper.joinSelectPage(page,queryWrapper,User.class);
        return resultPage;
    }

    public IPage<User> selectPageByData(String data, Page<User> page) {
        JoinLambdaWrapper<User> queryWrapper=new JoinLambdaWrapper<>(User.class);
        queryWrapper.leftJoin(Role.class,Role::getRoleId,User::getRoleId)
                .oneToOneSelect(User::getRole, Role.class)
                .apply("(CONCAT_WS('-',user_name,user_email,tb_role.role_name)) LIKE {0}","%"+data+"%")
                .end();
        IPage<User> resultPage=baseMapper.joinSelectPage(page,queryWrapper,User.class);
        return resultPage;
    }
    public User login(User user){
        System.out.println("开始登录");
        System.out.println(user.getUserEmail());
        UsernamePasswordAuthenticationToken token=new UsernamePasswordAuthenticationToken(user.getUserEmail(),user.getUserPassword());
        System.out.println(token.getPrincipal());
        Authentication authenticate = authenticationManager.authenticate(token);
        System.out.println(Objects.isNull(authenticate));
        // 判断是否验证成功
        if(Objects.isNull(authenticate)){
            throw new RuntimeException("用户名或密码错误");
        }
        // 在认证信息authenticate中获取登录成功后的用户信息
        LoginUser result = (LoginUser) authenticate.getPrincipal();
        result.getUser().setLastTime(new Date());
        updateOne(result.getUser());
        authorRedisServiceImpl.put("user-id-"+result.getUser().getUserId(),result);
        return result.getUser();
    }
    public User adminLogin(User user){
        JoinLambdaWrapper<User> queryWrapper=new JoinLambdaWrapper<>(User.class);
        queryWrapper.leftJoin(Role.class,Role::getRoleId,User::getRoleId)
                .oneToOneSelect(User::getRole, Role.class)
                .end();
        QueryWrapper<User> userQueryWrapper=new QueryWrapper<>();
        userQueryWrapper.eq("user_email",user.getUserEmail()).eq("user_password",Md5Utils.getMd5(user.getUserPassword()));
        queryWrapper.changeQueryWrapper(userQueryWrapper);
        User result=baseMapper.joinSelectOne(queryWrapper, User.class);
        if(result==null||result.getRole()==null)
            return null;
        return login(user);
    }
    public boolean logout(){
        System.out.println("开始退登");
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        // 判空，避免登录已过期导致异常
        if (ObjectUtils.isEmpty(authentication)) {
            return false;
        }
        // 从认证信息中获取登录用户数据
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        // 从登录用户数据中获取userId
        int userId = loginUser.getUser().getUserId();
        authorRedisServiceImpl.delete("user-id-"+userId);
        return true;
    }
}
